﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;

namespace 验证码识别
{
    class Verfiy
    {
        /// <summary>
        /// 进行彩色去噪点
        /// </summary>
        /// <param name="image">原位图</param>
        /// <returns>处理后位图</returns>
        public static Bitmap colorClear(Bitmap image)
        {
            //滤波计算
            //计算该像素点周围8个点及本身的RGB平均值，
            //计算这9个点到平均值的欧式距离。
            //从计算中选取最小的，用其RBG值代替该点的RGB值
            Color currentPixel;
            Bitmap imageResult = new Bitmap(image);
            for (int x = 0; x < image.Width; x++)
            {
                for (int y = 0; y < image.Height; y++)
                {
                    //取包括本身在内的9个点。并且计算其平均值
                    int Red = 0, Blue = 0, Green = 0;
                    int PointCount = 0;
                    for (int i = -1; i <= 1; i++)
                    {
                        for (int j = -1; j <= 1; j++)
                        {
                            //有像素点的话，叠加
                            if (x + i >= 0 && y + j >= 0 && x + i < image.Width && y + j < image.Height)
                            {
                                currentPixel = image.GetPixel(x, y);
                                Red += Convert.ToInt32(currentPixel.R);
                                Blue += Convert.ToInt32(currentPixel.B);
                                Green += Convert.ToInt32(currentPixel.G);
                                PointCount++;
                            }
                        }
                    }
                    Red = Red / PointCount;
                    Blue = Blue / PointCount;
                    Green = Green / PointCount;
                    //计算最小的欧式距离
                    double iDistance = 9999999; //默认无限大
                    int iX = x, iY = y; //欧式距离最小的那个色点，默认为本身
                    for (int i = -1; i <= 1; i++)
                    {
                        for (int j = -1; j <= 1; j++)
                        {
                            //有像素点的话，叠加
                            if (x + i >= 0 && y + j >= 0 && x + i < image.Width && y + j < image.Height)
                            {
                                currentPixel = image.GetPixel(x + i, y + j);
                                double iCurrentDistance = Math.Pow((Convert.ToDouble(currentPixel.R) - Red), 2) + Math.Pow(Convert.ToDouble(currentPixel.G) - Green, 2) + Math.Pow(Convert.ToDouble(currentPixel.B) - Blue, 2);
                                if (iCurrentDistance < iDistance)
                                {
                                    iX = x + i;
                                    iY = y + j;
                                    iDistance = iCurrentDistance;
                                }
                            }
                        }
                    }
                    imageResult.SetPixel(x, y, image.GetPixel(iX, iY));
                }
            }
            return imageResult;
        }
       /// <summary>
        /// 转化为灰度图像，进行二值化处理
       /// </summary>
       /// <param name="image">源图像</param>
       /// <param name="iThreshold">阈值</param>
       /// <returns>处理后</returns>
        public static Bitmap toGrey(Bitmap imageSrc,int iThreshold)
        {
            //函数将RGB三色表示转换为单比特的0或者1表示
            //利用公式 Grey=0.3*red+0.59*green+0.11*blue计算出灰度值
            //大于阈值iThreshold的就放为黑色，小于的话就为白色
            Color color;
            Bitmap image = new Bitmap(imageSrc);
            for (int x = 0; x < image.Width; x++)
            {
                for (int y = 0; y < image.Height; y++)
                {
                    color=image.GetPixel(x,y);
                    double iGrey = 0.3 * Convert.ToInt32(color.R) + 0.59 * Convert.ToInt32(color.G) + 0.11 * Convert.ToInt32(color.B);
                    if (iGrey < iThreshold)
                    {
                        image.SetPixel(x, y, Color.Black);
                    }
                    else
                    {
                        image.SetPixel(x, y, Color.White);
                    }
                }
            }
            return image;
        }
        /// <summary>
        /// 黑白去噪
        /// </summary>
        /// <param name="imageSrc">源图像</param>
        /// <param name="iPointWidth">像素宽度</param>
        /// <param name="iThreshold">阈值</param>
        /// <returns>处理后图像</returns>
        public static Bitmap blackClear(Bitmap imageSrc,int iPointWidth, int iThreshold)
        {
            //检查像素点，如果为白色0，跳过，如果为黑色1则进行噪点处理
            //统计周围的像素点，如果白色的个数超过阈值，则认为是噪点，将其设置为白色。
            Color color;
            Bitmap image = new Bitmap(imageSrc.Width + 2 * iPointWidth, imageSrc.Height + 2 * iPointWidth);
            //设置为全白，并拷贝图像
            Graphics g = Graphics.FromImage(image);
            g.Clear(Color.White);
            g.DrawImage(imageSrc,iPointWidth,iPointWidth);
            g.Dispose();
            Bitmap imageResult = new Bitmap(image);

            for (int x = iPointWidth-1; x < image.Width-iPointWidth+1; x++)
            {
                for (int y = iPointWidth-1; y < image.Height-iPointWidth+1; y++)
                {
                    
                    color = image.GetPixel(x, y);
                    int iWhiteCount = 0;
                    if (color.ToArgb() == Color.Black.ToArgb()) //黑色的话进行检查边上的。注意颜色对象不能直接比较。必须转换一下
                    {
                        for (int i = -iPointWidth; i <= iPointWidth; i++)
                        {
                            for (int j = -iPointWidth; j <= iPointWidth; j++)
                            {
                                //有像素点的话，统计
                                if (x + i >= 0 && y + j >= 0 && x + i < image.Width && y + j < image.Height)
                                {
                                    //该边际点为白色，且不是自身
                                    if (image.GetPixel(x + i, y + j).ToArgb() == Color.White.ToArgb() && i != 0 && j != 0)
                                    {
                                        iWhiteCount++;
                                    }
                                }
                            }
                        }
                        if (iWhiteCount > iThreshold) //白色点数大于阈值，认为是噪点
                        {
                            imageResult.SetPixel(x, y, Color.White);
                        }

                    }
                }
            }
            image.Dispose();
            return imageResult;
        }
    }
}
